﻿/*******************************************************
* Autor: Oleg Rukin aka Keyki
********************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Linq;
using System.Xml.Linq;
using Keyki.InitData;
using Keyki.WpfNefclas.Helpers;
using Microsoft.Win32;
using NefClass;

namespace Keyki.WpfNefclas
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow
	{
		private readonly INefClass _nefClass;

		private readonly Dictionary<string, FuzzySet> _fuzzySets;
		private readonly Dictionary<string, Modes> _modes;

		public MainWindow()
		{
			InitializeComponent();
			_fuzzySets = new Dictionary<string, FuzzySet>();
			_modes = new Dictionary<string, Modes>();

			_nefClass = new KeykiINefClass();
		}

		private void WindowLoaded(object sender, RoutedEventArgs e)
		{
			const string nefclassXML = "NefClass.Settings.xml";
			var doc = XDocument.Load(nefclassXML);
			var fuzzySets = from item in doc.Descendants()
											where item.Name == "FuzzySet"
											select item;

			var names = from fuzzySet in fuzzySets.Descendants()
									where fuzzySet.Name == "Name"
									select fuzzySet.Value;
			var inits = from fuzzySet in fuzzySets.Descendants()
									where fuzzySet.Name == "Init"
									select fuzzySet.Value;
			var trainers = from fuzzySet in fuzzySets.Descendants()
										 where fuzzySet.Name == "Trainer"
										 select fuzzySet.Value;
			var param = from fuzzySet in fuzzySets.Descendants()
									where fuzzySet.Name == "Params"
									select fuzzySet.Value;


			var choose = from item in doc.Descendants()
									 where item.Name == "ChooseRule"
									 select item.Value;

			var workers = from item in doc.Descendants()
										where item.Name == "Worker"
										select item;

			var workerName = from item in workers.Descendants()
											 where item.Name == "Name"
											 select item.Value;
			var workerMode = from item in workers.Descendants()
											 where item.Name == "Mode"
											 select item.Value;
			var workerAnt = from item in workers.Descendants()
											where item.Name == "Antecedent"
											select item.Value;

			int countFuzzySet = names.Count();
			int countWorker = workerName.Count();

			for (int i = 0; i < countFuzzySet; ++i)
			{
				_fuzzySets.Add(names.ElementAtOrDefault(i),
											 new FuzzySet
												{
													Init = inits.ElementAtOrDefault(i),
													Trainer = trainers.ElementAtOrDefault(i),
													Params = Int32.Parse(param.ElementAtOrDefault(i))
												});
			}

			for (int i = 0; i < countWorker; ++i)
			{
				_modes.Add(workerMode.ElementAtOrDefault(i),
									 new Modes
										{
											Worker = workerName.ElementAtOrDefault(i),
											Antecedent = workerAnt.ElementAtOrDefault(i)
										});
			}

			foreach (var keyValue in _fuzzySets)
			{
				FuzzySetList.Items.Add(keyValue.Key);
			}

			foreach (var element in choose)
			{
				RuleChoose.Items.Add(element);
			}

			SigmaValue.PreviewTextInput += InputHelper.FloatTextInput;
			LearnPercent.PreviewTextInput += InputHelper.FloatTextInput;
			ErrorMax.PreviewTextInput += InputHelper.FloatTextInput;
			RulesMax.PreviewTextInput += InputHelper.DecimalTextInput;
			EpouchMax.PreviewTextInput += InputHelper.DecimalTextInput;

			Core.InitData.WorkerHandler = _modes["CPU"].Worker;
			Core.InitData.AntecedentsHandler = _modes["CPU"].Antecedent;

		}

		private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Core.Logger.Close();
			try
			{
				var filename = Core.InitData.FileName;
				int last = filename.LastIndexOf('.');
				filename = filename.Remove(last);
				SInitData.Serialize(ref Core.InitData, filename + ".xml");
				SOutData.Serialize(ref Core.OutData, filename + "_out.data");
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		private void BtnOpenClick(object sender, RoutedEventArgs e)
		{
			var openFileDialog1 = new OpenFileDialog
															{
																InitialDirectory = Directory.GetCurrentDirectory(),
																Filter = "txt files (*.txt)|*.txt|xml files (*.xml)|*.xml",
																FilterIndex = 2,
																RestoreDirectory = true
															};

			openFileDialog1.ShowDialog();
			Core.InitData.FileName = openFileDialog1.FileName;
			if (!String.IsNullOrEmpty(Core.InitData.FileName))
			{
				var filter = openFileDialog1.FilterIndex;
				if (filter == 2)
				{
					var filename = Core.InitData.FileName;
					SInitData.Deserialize(ref Core.InitData, filename);
					int index = filename.LastIndexOf('.');
					filename = filename.Remove(index);
					filename = filename.Insert(index, "_out.data");
					SOutData.Deserialize(ref Core.OutData, filename);

					isAny.IsChecked = Core.InitData.IsAny;
					isSafe.IsChecked = Core.InitData.IsSafeState;
					isStep.IsChecked = Core.InitData.IsDynamicStep;
					isRandomize.IsChecked = Core.InitData.Randomize;
					isRepeats.IsChecked = Core.InitData.NoRepeats;
					LearnPercent.Text = Core.InitData.Sigma.ToString();
					RulesMax.Text = Core.InitData.RullesCount.ToString();
					EpouchMax.Text = Core.InitData.MaxEpouch.ToString();
					ErrorMax.Text = Core.InitData.MaxError.ToString();
					LearnPercent.Text = Core.InitData.LearnPercent.ToString();

					FuzzySetList.SelectedValue = Core.InitData.FuzzySetHandler;
					RuleChoose.SelectedValue = Core.InitData.ChooseRuleHandler;
				}
				FileName.Text = Core.InitData.FileName;
				var initParams = new InitParams(filter == 2);
				initParams.ShowDialog();
			}
		}

		//BtnOpen_Click

		private void FuzzySetListSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
		{
			var name = e.AddedItems[0];
			FuzzySet fuzzySet = _fuzzySets[name.ToString()];
			Core.InitData.FuzzySetHandler = name.ToString();
			Core.InitData.ParamsCount = fuzzySet.Params;
			Core.InitData.InitDataHandler = fuzzySet.Init;
			Core.InitData.TrainerHandler = fuzzySet.Trainer;
		}

		private void RuleChooseSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
		{
			var name = e.AddedItems[0];
			Core.InitData.ChooseRuleHandler = name.ToString();
		}

		private void IsRandomizeChecked(object sender, RoutedEventArgs e)
		{
			isRepeats.IsEnabled = isRandomize.IsChecked.GetValueOrDefault(false);
		}

		private void BtnStartClick(object sender, RoutedEventArgs e)
		{
			if (Core.InitData.AntecedentsHandler != null && Core.InitData.TrainerHandler != null
				&& Core.InitData.WorkerHandler != null && Core.InitData.InitDataHandler != null
				&& Core.InitData.ChooseRuleHandler != null && !String.IsNullOrEmpty(Core.InitData.FileName))
			{
				Core.InitData.IsAny = isAny.IsChecked.GetValueOrDefault(false);
				Core.InitData.IsSafeState = isSafe.IsChecked.GetValueOrDefault(false);
				Core.InitData.IsDynamicStep = isStep.IsChecked.GetValueOrDefault(false);
				Core.InitData.Randomize = isRandomize.IsChecked.GetValueOrDefault(false);
				Core.InitData.NoRepeats = isRepeats.IsChecked.GetValueOrDefault(false);
				Core.InitData.Sigma = Single.Parse(SigmaValue.Text);
				Core.InitData.RullesCount = Int32.Parse(RulesMax.Text);
				Core.InitData.MaxEpouch = Int32.Parse(EpouchMax.Text);
				Core.InitData.MaxError = Single.Parse(ErrorMax.Text);
				Core.InitData.LearnPercent = Single.Parse(LearnPercent.Text);

				Core.InitData.LearnCount = Math.Ceiling(Core.InitData.ElementCount * Core.InitData.LearnPercent);
				Core.OutData = _nefClass.NefClass(Core.InitData);
				//showGraph.IsEnabled = true;
				//GetRules.IsEnabled = true;
				Core.OutData.Error /= Core.InitData.ElementCount;
				Core.Logger.WriteLine(String.Format("FuzzySet;{0};ChooseRule;{1};Randomize;{2};IsAny;{3};IsSafeState;{4};" +
																						"IsDynamicStep{5};Sigma;{6};RullesCount;{7};Error;{8};Time;{9}",
																						Core.InitData.FuzzySetHandler,
																						Core.InitData.ChooseRuleHandler,
																						Core.InitData.Randomize, Core.InitData.IsAny, Core.InitData.IsSafeState,
																						Core.InitData.IsDynamicStep, Core.InitData.Sigma, Core.InitData.RullesCount,
																						Core.OutData.Error, Core.OutData.Time));

				MessageBox.Show("Time of work " + Core.OutData.Time + "\n Error " + Core.OutData.Error);
			}
			else
			{
				MessageBox.Show("Some parameters doesn't set properly, NefClass can't start work");
			}
		}

		private void GetRulesClick(object sender, RoutedEventArgs e)
		{
			var showRules = new ShowRules();
			showRules.ShowDialog();
		}

		//for Test
		/*
				private void InitData(ref SInitData initData)
				{
					initData.FeatureCount	= 4;
					initData.LinguisticVariables = 3;
					initData.LinguisticVariablesNames = new string[3];
					initData.LinguisticVariablesNames[0] = "small";
					initData.LinguisticVariablesNames[1] = "medium";
					initData.LinguisticVariablesNames[2] = "large";

					initData.ClassNames = new string[3];
					initData.ClassNames[0] = "setosa";
					initData.ClassNames[1] = "versicolor";
					initData.ClassNames[2] = "virginica";

					initData.ClassCount		= 4;
					initData.ElementCount	= 150;
					initData.ParamsCount = 2;
					initData.RullesCount = 12;
					initData.LearnPercent	= 0.70f;
					initData.LearnCount = Math.Ceiling( initData.ElementCount * initData.LearnPercent);
					initData.IsAny = true;
					initData.Randomize = true;
					initData.NoRepeats = true;
					initData.FileName = "IRIS.txt";

					initData.FuzzySetHandler			= "GausFuzzySet";//TriangleFuzzySet GausFuzzySet TrapezeFuzzySet
					initData.AntecedentsHandler	= "SimpleAntecedent";
					initData.InitDataHandler			= "GausInit";//TriangleInit GausInit TrapezeInit
					initData.ChooseRuleHandler		= "BestForClassRules";//AllRules; BestRules; BestForClassRules;
					initData.TrainerHandler			= "GausTrainer";//TriangleTrainer GausTrainer TrapezeTrainer GradientTrainer
					initData.WorkerHandler				= "SimpleWorker";

					initData.Sigma = 0.07f;
					initData.MaxEpouch = 100;
					initData.MaxError  = 0.05f;
				}*/
		//InitData
	}
}
